package cn.sstech.IM.webserver.user.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;

import cn.sstech.IM.constant.Constants;
import cn.sstech.IM.server.connertor.ImConnertor;
import cn.sstech.IM.server.group.ServerGroupManager;
import cn.sstech.IM.server.model.MessageWrapper;
import cn.sstech.IM.server.model.Session;
import cn.sstech.IM.server.model.proto.MessageBodyProto;
import cn.sstech.IM.server.model.proto.MessageProto;
import cn.sstech.IM.server.session.impl.SessionManagerImpl;
import cn.sstech.IM.util.result.DefaultResult;
import cn.sstech.IM.util.result.IBaseResult;
import cn.sstech.IM.util.result.RetResultCode;
import cn.sstech.IM.webserver.user.dao.UserChatDao;
import cn.sstech.IM.webserver.user.dao.UserDepartmentDao;
import cn.sstech.IM.webserver.user.model.Group;
import cn.sstech.IM.webserver.user.model.GroupMember;
import cn.sstech.IM.webserver.user.model.ImGroupUserData;
import cn.sstech.IM.webserver.user.model.NoticeEntity;
import cn.sstech.IM.webserver.user.model.UserAccountEntity;
import cn.sstech.IM.webserver.user.model.UserFriend;
import cn.sstech.IM.webserver.user.model.UserInfoEntity;
import cn.sstech.IM.webserver.user.model.UserMessageEntity;
import cn.sstech.IM.webserver.user.service.UserChatService;
import io.netty.channel.group.ChannelGroup;

@Service("userChatServiceImpl")
public class UserChatServiceImpl implements UserChatService{

	@Autowired
	private UserDepartmentDao userDepartmentDao;
	@Autowired
	UserInfoServiceImpl userInfoServiceImpl;
	
	@Autowired
	UserChatDao userChatDao;
	
	@Autowired
	private SessionManagerImpl sessionManager;
	
	@Autowired
	private ImConnertor connertor;
	
	@Override
	public IBaseResult addFriend(UserFriend userFriend) {
		userDepartmentDao.addFriend(userFriend);
		return DefaultResult.buildSuccessResult();
	}

	@Override
	public IBaseResult delFriend(UserFriend userFriend) {
		Integer isFriend = userDepartmentDao.isFriend(userFriend);
		
		if(isFriend >= 1){
			userDepartmentDao.delFriend(userFriend);
		}
		return DefaultResult.buildSuccessResult();
	}

	@Override
	public IBaseResult addUserGroup(Group group, Long userId) {
		group.setCreateUserId(userId);
		userChatDao.addGroup(group);
		
		List<GroupMember> groupMembers = new ArrayList<GroupMember>();
		GroupMember groupMember = new GroupMember();
		groupMember.setGroupId(group.getId());
		groupMember.setMemberType(Constants.GroupConfig.MANAGER);
		groupMember.setUserId(userId);
		group.setGroupMember(groupMembers);
		
		userChatDao.addGroupMember(group);
		
		
		return DefaultResult.buildSuccessResult();
	}

	@Override
	public IBaseResult delUserGroup(Group goup, Long userId) {
		Integer isGroupManager = userChatDao.isGroupManager(goup,userId);
		
		if(null != isGroupManager && isGroupManager > 0){
			userChatDao.delAllGroupMember(goup);
			userChatDao.delGroup(goup);
		}
		else{
			return DefaultResult.buildFailedResult(RetResultCode.E10001);
		}
		
		return DefaultResult.buildSuccessResult();
	}

	@Override
	public IBaseResult getUserGroup(Long userId) {
		List<Group> group = userChatDao.getGroupInfoByUserId(userId);
		return DefaultResult.buildSuccessResult(group);
	}

	@Override
	public IBaseResult addGroupMember(Group group, Long userId) {
		Integer isGroupManager = userChatDao.isGroupManager(group,userId);
		
		if(null != isGroupManager && isGroupManager > 0){
			if(null == group.getGroupMember()){
				return DefaultResult.buildFailedResult(RetResultCode.E10002);
			}
			userChatDao.addGroupMember(group);
		}
		else{
			return DefaultResult.buildFailedResult(RetResultCode.E10001);
		}
		
		return DefaultResult.buildSuccessResult();
	}

	@Override
	public IBaseResult delGroupMember(Group group, Long userId) {
		Integer isGroupManager = userChatDao.isGroupManager(group,userId);
		
		if(null != isGroupManager && isGroupManager > 0){
			if(null == group.getGroupMember() || group.getGroupMember().isEmpty()){
				return DefaultResult.buildFailedResult(RetResultCode.E10002);
			}
			userChatDao.delGroupMember(group);
		}
		else{
			return DefaultResult.buildFailedResult(RetResultCode.E10001);
		}
		
		return DefaultResult.buildSuccessResult();
	}

	@Override
	public IBaseResult pullOfflineMsg(Long userId) {
		if(null == userId){
			return DefaultResult.buildFailedResult(RetResultCode.E10003);
		}
		
		List<UserMessageEntity> result = userChatDao.getGroupOfflineMessageList(userId);
		
		return DefaultResult.buildSuccessResult(result);
		
	}

	@Override
	public List<Group> getUserGroupData(Long userId) {
		return userChatDao.getGroupInfoByUserId(userId);
	}

	@Override
	public List<ImGroupUserData> getSysServerGroups() {
		List<ImGroupUserData> result = userChatDao.getSysServerGroups();
		
		if(null == result){
			return new ArrayList<ImGroupUserData>();
		}
		else{
			return result;
		}
		
	}

	@Override
	public IBaseResult noticeAdd(NoticeEntity noticeEntity, Long userId, String account) {
		if(null == userId ){
			return DefaultResult.buildFailedResult(RetResultCode.E10003);
		}
		if(!userId.equals(noticeEntity.getSenderId())){
			return DefaultResult.buildFailedResult(RetResultCode.E10005);
		}
		
		if(Constants.NoticeType.ADD_USER.equals(noticeEntity.getType()) ){
			userChatDao.noticeAdd(noticeEntity);
			
			//通知在线用户
			UserInfoEntity receiver = userInfoServiceImpl.queryObject(noticeEntity.getReceiverId());
			if(null == receiver){
				return DefaultResult.buildFailedResult(RetResultCode.E10006);
			}
			boolean  exist = sessionManager.exist(receiver.getUid().toString());
			
			if(exist){
				MessageProto.Model.Builder builder = MessageProto.Model.newBuilder();
				builder.setCmd(Constants.CmdType.MESSAGE);
				builder.setSender(account);
				builder.setMsgtype(Constants.ProtobufType.NOTIFY);
		         MessageBodyProto.MessageBody.Builder  msg =  MessageBodyProto.MessageBody.newBuilder();
		         msg.setContent(JSON.toJSONString(noticeEntity));
		         builder.setContent(msg.build().toByteString());
		         
				MessageWrapper  msgWrapper = new MessageWrapper(MessageWrapper.MessageProtocol.NOTIFY, receiver.getUid().toString(), null,builder);
				connertor.pushMessage(msgWrapper);
			}
		}
		else if (Constants.NoticeType.JOIN_GROUP.equals(noticeEntity.getType()) ){
			//获取群的所有管理员
			List<UserInfoEntity> manager = userChatDao.getAllManagerByGroupId(noticeEntity.getGroupId());
			
			List<NoticeEntity> notices = new ArrayList<NoticeEntity>();
			for(UserInfoEntity u : manager){
				NoticeEntity noticeNode = new NoticeEntity();
				BeanUtils.copyProperties(noticeEntity, noticeNode);
				noticeNode.setReceiverId(u.getId());
				notices.add(noticeNode);
			}
			
			if(!notices.isEmpty()){
				userChatDao.noticeAddAll(notices);
			}
			
			
			//通知所有在线管理员
			for(UserInfoEntity u : manager){
				boolean  exist = sessionManager.exist(u.getUid().toString());
 				if(exist){
					MessageProto.Model.Builder builder = MessageProto.Model.newBuilder();
					builder.setCmd(Constants.CmdType.MESSAGE);
					builder.setSender(account);
					builder.setMsgtype(Constants.ProtobufType.NOTIFY);
			         MessageBodyProto.MessageBody.Builder  msg =  MessageBodyProto.MessageBody.newBuilder();
			         msg.setContent(JSON.toJSONString(noticeEntity));
			         builder.setContent(msg.build().toByteString());
					
					MessageWrapper  msgWrapper = new MessageWrapper(MessageWrapper.MessageProtocol.NOTIFY, u.getUid().toString(), null,builder);
					connertor.pushMessage(msgWrapper);
				}
			}
		}

		
		return DefaultResult.buildSuccessResult();
	}

	@Override
	public Collection<? extends NoticeEntity> getNoticeByUserId(Long userId) {
		
		List<NoticeEntity> notices = userChatDao.getNoticeByUserId(userId);
		
		return notices;
	}

	@Override
	public IBaseResult noticeReaded(Long noticeId, Long userId) {
		if(null == userId ){
			return DefaultResult.buildFailedResult(RetResultCode.E10003);
		}
		
		NoticeEntity notice = userChatDao.getNoticeById(noticeId);
		if(null != notice){
			if(!userId.equals(notice.getReceiverId()) ){
				return DefaultResult.buildFailedResult(RetResultCode.E10005);
			}
			
			if(Constants.NoticeType.JOIN_GROUP.equals( notice.getType())){
				userChatDao.joinGroupNoticeReaded(notice);
			}
			else if(Constants.NoticeType.ADD_USER.equals( notice.getType())){
				userChatDao.noticeReaded(notice);
				UserFriend friend = new UserFriend();
				friend.setFriendId(notice.getReceiverId());
				friend.setUserId(notice.getSenderId().toString());
				this.addFriend(friend);
			}
		}
		
		return DefaultResult.buildSuccessResult();
	}

	@Override
	public IBaseResult delFriend(NoticeEntity noticeEntity, Long userId) {
		if(null != noticeEntity){
			if(!userId.equals(noticeEntity.getSenderId()) ){
				return DefaultResult.buildFailedResult(RetResultCode.E10005);
			}
			
			userChatDao.delFriend(noticeEntity);
			
			return DefaultResult.buildSuccessResult();
		}
		else {
			return DefaultResult.buildFailedResult(RetResultCode.E10003);
		}
	}

	@Override
	public IBaseResult delGroupMember(NoticeEntity noticeEntity, Long userId) {
		if(null != noticeEntity && null != noticeEntity.getGroupId()){
			if(!userId.equals(noticeEntity.getSenderId()) ){
				return DefaultResult.buildFailedResult(RetResultCode.E10005);
			}
			
			List<UserInfoEntity> manager = userChatDao.getAllManagerByGroupId(noticeEntity.getGroupId());
			
			if(manager==null || manager.isEmpty()){
				return DefaultResult.buildFailedResult(RetResultCode.E10004);
			}
			
			for(UserInfoEntity user : manager){
				if(userId.equals(user.getId())){
					userChatDao.delGroupMemberByNotice(noticeEntity);
					break;
				}
			}
			
			//将被删除用户从群channal中剔除
			UserInfoEntity userInfoEntity = userInfoServiceImpl.queryObject(noticeEntity.getReceiverId());
			Session session = sessionManager.getSession(userInfoEntity.getUid().toString());
			if(null != session ){
				ServerGroupManager.removeChannel(session.getSession(), noticeEntity.getGroupId());
			}
			
			return DefaultResult.buildSuccessResult();
		}
		else {
			return DefaultResult.buildFailedResult(RetResultCode.E10003);
		}
	}

}
